package com.lemon.blog.system.service.impl;

import com.lemon.blog.system.domain.BlBlog;
import com.lemon.blog.system.domain.BlBlogTag;
import com.lemon.blog.system.domain.BlTag;
import com.lemon.blog.system.domain.BlType;
import com.lemon.blog.system.mapper.BlBlogMapper;
import com.lemon.blog.system.mapper.BlBlogTagMapper;
import com.lemon.blog.system.mapper.BlTagMapper;
import com.lemon.blog.system.mapper.BlTypeMapper;
import com.lemon.blog.system.service.IBlBlogService;
import com.lemon.common.core.constant.Constants;
import com.lemon.common.core.constant.UserConstants;
import com.lemon.common.core.exception.ServiceException;
import com.lemon.common.security.service.BaseServiceImpl;
import com.lemon.common.security.utils.OptEntityUtils;
import com.lemon.common.datascope.annotation.DataScope;
import com.lemon.common.security.utils.SecurityUtils;
import com.lemon.system.api.RemoteSearchService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * 包名称：com.lemon.blog.service.impl
 * 类名称：BlBlogServiceImpl
 * 类描述：博客管理Service业务层处理
 * 创建人：@author huangpeng
 * 创建时间：2022年04月25日 17:12
 */
@Service
public class BlBlogServiceImpl extends BaseServiceImpl<BlBlog> implements IBlBlogService {

    public static final Logger logger = LoggerFactory.getLogger(BlBlogServiceImpl.class);

    @Autowired
    private BlBlogMapper blBlogMapper;

    @Autowired
    private BlTagMapper blTagMapper;

    @Autowired
    private BlBlogTagMapper blBlogTagMapper;

    @Autowired
    private BlTypeMapper blTypeMapper;

    @Override
    @DataScope(userAlias = "b")
    public List<BlBlog> selectBlBlogList(BlBlog blBlog) {
        return blBlogMapper.selectBlBlogList(blBlog);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(BlBlog blBlog) {
        if (blBlog.getStatus().equals(Constants.STR_ZERO) && !blBlog.getApprovalStatus().equals(Constants.STR_THREE)) {
            throw new ServiceException("文章未发布前，审批状态只能选无");
        }
        blBlog.setAdminId(SecurityUtils.getLoginUser().getUserid());
        blBlog.setUserId(SecurityUtils.getLoginUser().getUserid());
        OptEntityUtils.preInsert(blBlog);
        int count = blBlogMapper.insertSelective(blBlog);
        insertBlogTagRel(blBlog);
        increaseTypeBlogCount(blBlog.getBlogType());
        return count;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int update(BlBlog blBlog) {
        // 更新文章后，文章状态自动变成待复核
        blBlog.setApprovalStatus(Constants.STR_TWO);
        checkAuth(blBlog);
        OptEntityUtils.preUpdate(blBlog);
        clearBlogTagRel(blBlog.getId());
        insertBlogTagRel(blBlog);
        decreaseTypeBlogCount(blBlog.getId());
        increaseTypeBlogCount(blBlog.getBlogType());
        return blBlogMapper.updateByPrimaryKeySelective(blBlog);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByBatch(Long[] ids) {
        for (Long blogId : ids) {
            checkAuth(new BlBlog(blogId));
            clearBlogTagRel(blogId);
        }
        return blBlogMapper.deleteByBatch(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByPrimaryKey(Long id) {
        checkAuth(new BlBlog(id));
        clearBlogTagRel(id);
        return blBlogMapper.deleteByPrimaryKey(id);
    }

    /**
     * 插入博客标签关联信息
     * @Title: insertBlogTagRel
     * @Description: 插入博客标签关联信息
     * @param blBlog 博客数据
     * @throws:
     * @author: huangpeng
     * @Date: 2022/5/1 18:09
     */
    private void insertBlogTagRel(BlBlog blBlog) {
        List<BlTag> tagList = blBlog.getTagList();
        for (BlTag nTag : tagList) {
            BlTag blTag = blTagMapper.selectByPrimaryKey(nTag.getId());
            blTag.setTagBlogCount(blTag.getTagBlogCount() + 1);
            OptEntityUtils.preUpdate(blTag);
            blTagMapper.updateByPrimaryKeySelective(blTag);

            BlBlogTag blogTag = new BlBlogTag();
            blogTag.setBlogId(blBlog.getId().toString());
            blogTag.setTagId(nTag.getId());
            OptEntityUtils.preInsert(blogTag);
            blBlogTagMapper.insert(blogTag);
        }
    }

    /**
     * 清除原有标签信息
     * @Title: clearBlogTagRel
     * @Description: 清除原有标签信息
     * @param blogId 博客id
     * @return: void
     * @throws:
     * @author: huangpeng
     * @Date: 2022/5/1 18:29
     */
    private void clearBlogTagRel(Long blogId) {
        // 清除原有标签信息
        List<BlBlogTag> blogTagList = blBlogTagMapper.selectByBlogId(blogId.toString());
        blogTagList = blogTagList.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing((BlBlogTag::getTagId)))), ArrayList::new)
        );
        for (BlBlogTag blogTag : blogTagList) {
            BlTag blTag = blTagMapper.selectByPrimaryKey(blogTag.getTagId());
            if (blTag != null) {
                blTag.setTagBlogCount(blTag.getTagBlogCount() > 0 ? (blTag.getTagBlogCount() - 1) : 0);
                OptEntityUtils.preUpdate(blTag);
                blTagMapper.updateByPrimaryKeySelective(blTag);
            }
        }
        blBlogTagMapper.deleteByBlogId(blogId.toString());
    }

    /**
     * 分类的文章数量加1
     * @Title: increaseTypeBlogCount
     * @Description: 分类的文章数量加1
     * @param blogType 博客类型
     * @return: void
     * @throws:
     * @author: huangpeng
     * @Date: 2022/5/2 1:21
     */
    private void increaseTypeBlogCount(String blogType) {
        BlType blType = blTypeMapper.selectBlTypeByTypeCode(blogType);
        if (blType != null) {
            blType.setTypeBlogCount(blType.getTypeBlogCount() + 1);
            OptEntityUtils.preUpdate(blType);
            blTypeMapper.updateByPrimaryKeySelective(blType);
        }
    }

    /**
     * 分类文章数量减1
     * @Title: decreaseTypeBlogCount
     * @Description: 分类文章数量减1
     * @param blogId 博客id
     * @return: void
     * @throws:
     * @author: huangpeng
     * @Date: 2022/5/2 1:24
     */
    private void decreaseTypeBlogCount(Long blogId) {
        BlBlog blBlog = blBlogMapper.selectByPrimaryKey(blogId);
        BlType blType = blTypeMapper.selectBlTypeByTypeCode(blBlog.getBlogType());
        if (blType != null && blType.getTypeBlogCount() > 0) {
            blType.setTypeBlogCount(blType.getTypeBlogCount() - 1);
            OptEntityUtils.preUpdate(blType);
            blTypeMapper.updateByPrimaryKeySelective(blType);
        }
    }

    /**
     * 校验是否有编辑或者删除权限
     * @Title: checkAuth
     * @Description: 校验是否有编辑或者删除权限
     * @param blBlog
     * @return: void
     * @throws:
     * @author: huangpeng
     * @Date: 2023/4/30 20:45
     */
    private void checkAuth(BlBlog blBlog) {
        BlBlog existBlog = blBlogMapper.selectByPrimaryKey(blBlog.getId());
        if (!SecurityUtils.getUserId().equals(existBlog.getId()) && !UserConstants.SUPER_ADMIN.equals(SecurityUtils.getUsername())) {
            throw new ServiceException("无权限操作当前数据！");
        } else {
            // 不允许更改作者
            blBlog.setAdminId(null);
            blBlog.setUserId(null);
        }
    }
}
